/****************************************************************
 *  * *Process the common configure interface
 *  * *
 *  * *file name:configproc.cpp
 *  * *
 *  * *Copyright (C)2012 Cisco webex.
 *  * *All rights reserved
 *  * *
 *  * *Author:zhenye
 *  * *Date  :2013-04-27
 *  * *
 *  * ****************************************************************/

#include <map>
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>

#include "mct_system.h"
#include "errcode.h"
#include "configproc.h"

using namespace config_mct;

/* resource management map */
static std::map<std::string, std::string> g_oCfgCAMEResMgr;

/*
* get the config value by item
*/
LONG config_mct::getConfigItemValue(const std::string& strFileName, const std::string& strConfItem, std::string& strValue)
{
    LONG lRet = ERR_NOT_EXIST_ITEM;
    LONG lPos;
    BOOL_T bFail;
    CHAR szLine[CAME_CONFITEM_LEN_MAX];
    std::string strTrimStr;
    std::ifstream oFileReadStream;
    oFileReadStream.open(strFileName.c_str());
    bFail = (BOOL_T) oFileReadStream.fail();
    if (BOOL_TRUE == bFail)
    {
        return ERR_OPEN_FILE;
    }

    /* circulate get the lines content of file */
    while (!oFileReadStream.eof())
    {
        (void)oFileReadStream.getline(szLine, CAME_CONFITEM_LEN_MAX);
        strTrimStr = szLine;
        config_mct::trimString(strTrimStr);
        if ("" == strTrimStr)
        {
            continue;
        }

        /* process the '#' annotation line */
        if ('#' == *strTrimStr.c_str())
        {
            continue;
        }

        /* find config position by itme key */
        lPos = strTrimStr.find(strConfItem);
        if (0 != lPos)
        {
            /* not right lines for that item config */
            continue;
        }

        /*trim the item key, then trim blank or tab of string header or tail */
        strValue = strTrimStr.substr(strConfItem.length());
        config_mct::trimString(strValue);
        if ("" == strValue)
        {
            continue;
        }

        /*trim '=' char */
        if ('=' != *strValue.c_str())
        {
            continue;
        }

        /* trim blank or tab of string header or tail */
        (void)strValue.erase(0, 1);
        config_mct::trimString(strValue);
        lRet = ERR_COMMON_SUCCEED;
        break;
    }

    oFileReadStream.close();
    return lRet;
}

/*
* get the config int value by item
*/
LONG config_mct::getConfigIntValue( const std::string& strConfFile, const std::string& strConfigItem, LONG& lValue )
{
    std::string strValue;
    CHAR *stop = NULL;
    LONG lRet = config_mct::getConfigItemValue(strConfFile, strConfigItem, strValue);
    if (ERR_COMMON_SUCCEED == lRet)
    {
        if(!config_mct::isDigit(strValue))
        {
            return ERR_INVALID_ITEM_VALUE;
        }

        LONG lVal = MCT_strtol(strValue.c_str(), &stop, 10);
        if((NULL != stop) && (*stop != '\0'))
        {
            return ERR_INVALID_ITEM_VALUE;
        }
        else
        {
            lValue = lVal;
            return ERR_COMMON_SUCCEED;
        }
    }
    return lRet;
}

/*
* trim the blank or tab of string header or tail
*/
VOID config_mct::trimString(std::string& strTrimStr)
{
    LONG lStartPos;
    LONG lEndPos;
    lStartPos = strTrimStr.find_first_not_of(" \t");
    lEndPos = strTrimStr.find_last_not_of(" \t");
    if ((lStartPos < 0) || (lEndPos < 0))
    {
        strTrimStr = "";
        return;
    }

    if ((strTrimStr.length() - 1) != ((ULONG)lEndPos))
    {
        strTrimStr.erase(lEndPos + 1);
    }

    if (0 != lStartPos)
    {
        strTrimStr.erase(0, lStartPos);
    }
}

/*
* judge the chars is digit
*/
BOOL_T config_mct::isDigit(const CHAR* pszStr, LONG Len)
{
    if ((NULL == pszStr) || (0 == Len))
    {
        return BOOL_FALSE;
    }

    if (('-' != pszStr[0]) && ('+' != pszStr[0]) && (('0' > pszStr[0]) || ('9' < pszStr[0])))
    {
        return BOOL_FALSE;
    }

    for (int i = 1; i < Len; i++)
    {
        if (('0' > pszStr[i]) || ('9' < pszStr[i]))
        {
            return BOOL_FALSE;
        }
    }

    return BOOL_TRUE;
}

/*
* judge the string is digit
*/
BOOL_T config_mct::isDigit(const std::string& strDigitParam)
{
    return isDigit(strDigitParam.c_str(), strDigitParam.length());
}

/* init the config resource management map */
VOID config_mct::initResMapMgr(VOID)
{
    g_oCfgCAMEResMgr.clear();
}

/* add the resource of the file to the config resource management map */
BOOL_T config_mct::addResFile(const std::string& strResFileName)
{
    LONG lPosition;
    std::string strFirst;
    std::string strSecond;
    std::string strTrimStr;
    CHAR szLine[CAME_CONFITEM_LEN_MAX];
    std::ifstream oFileReadStream;
    oFileReadStream.open(strResFileName.c_str());
    if (oFileReadStream.fail())
    {
        return BOOL_FALSE;
    }

    /* circulate get the lines content of file */
    while (!oFileReadStream.eof())
    {
        (void)oFileReadStream.getline(szLine, CAME_CONFITEM_LEN_MAX);
        strTrimStr = szLine;
        config_mct::trimString(strTrimStr);

        /* process the '#' annotation line */
        if ('#' == *strTrimStr.c_str())
        {
            continue;
        }

        /* find the char of '='  */
        lPosition = strTrimStr.find("=");
        if (lPosition <= 0)
        {
            continue;
        }

        /* get the substring ahead the char '=' */
        strFirst = strTrimStr.substr(0, lPosition);
        config_mct::trimString(strFirst);
        /* get the substring behind the char '=' */
        strSecond = strTrimStr.substr(lPosition + 1);
        /* erase '\r' '\n' */
        while ((0 != strSecond.length()) && (('\r' == *(strSecond.end()-1)) || ('\n' == *(strSecond.end()-1))))
        {
            strSecond.erase((strSecond.end()-1));
        }
        config_mct::trimString(strSecond);
        (void)g_oCfgCAMEResMgr.insert(std::pair<std::string, std::string>(strFirst, strSecond));
    }

    oFileReadStream.close();
    return BOOL_TRUE;
}

/*
* get resource value by key
*/
std::string* config_mct::getResByKey(const std::string& strKey)
{
    std::map<std::string, std::string>::iterator oIterator;
    oIterator = g_oCfgCAMEResMgr.find(strKey);
    if (oIterator == g_oCfgCAMEResMgr.end())
    {
        return NULL;
    }

    return &oIterator->second;
}

/*
* get resource value by key, if not exist use the default
*/
std::string config_mct::getResByKey(const std::string& strKey, const std::string& strDefault)
{
    std::map<std::string, std::string>::iterator oIterator;
    oIterator = g_oCfgCAMEResMgr.find(strKey);
    if (oIterator == g_oCfgCAMEResMgr.end())
    {
        return strDefault;
    }

    return oIterator->second;
}

/*
* get int resource value by key, if not exist use the default
*/
LONG config_mct::getIntResByKey(const std::string& strKey, LONG lDefault)
{
    char *stop = NULL;
    std::map<std::string, std::string>::iterator oIterator;
    oIterator = g_oCfgCAMEResMgr.find(strKey);
    if (oIterator == g_oCfgCAMEResMgr.end())
    {
        return lDefault;
    }

    if(!config_mct::isDigit(oIterator->second))
    {
        return lDefault;
    }

    LONG lVal = (LONG) MCT_strtol(oIterator->second.c_str(), &stop, 10);
    if((NULL != stop) && (*stop != '\0'))
    {
        return lDefault;
    }
    else
    {
        return lVal;
    }
}

VOID config_mct::string_toupper(CHAR *pcInput, CHAR *pcOutput)
{
    if ((NULL == pcInput) || (NULL == pcOutput))
    {
        return;
    }

    do
    {
        *pcOutput++ = MCT_toupper(*pcInput);
    }while (0 != *pcInput++);

    return;
}

LONG config_mct::getCommonInputParam(CHAR *szInputParam, CHAR *pcFilter1, CHAR *pcFilter2, ULONG ulType, VOID *pResult)
{
    CHAR *strFind = NULL;
    CHAR szUpperFilter1[MAX_CFG_ITEM_LEN] = {0};
    CHAR szUpperFilter2[MAX_CFG_ITEM_LEN] = {0};
    CHAR szParam[MAX_CFG_ITEM_LEN] = {0};
    CHAR *pcStop = NULL;
    BOOL_T bFind = BOOL_FALSE;
    LONG lRet = ERR_NOT_EXIST_ITEM;
    LONG lTmpLen = 0;

    if ((NULL == szInputParam) || (NULL == pcFilter1) || (NULL == pResult) )
    {
        return ERR_INPUT_PARAM_INFO;
    }

    string_toupper(pcFilter1, szUpperFilter1);
    if (NULL != pcFilter2)
    {
        string_toupper(pcFilter2, szUpperFilter2);
    }

    /* check the filters string */
    lTmpLen = MCT_strnlen(pcFilter1, MAX_CFG_ITEM_LEN);
    if ((NULL != (strFind = (CHAR *) MCT_strnstr(szInputParam, pcFilter1, lTmpLen))) ||
        (NULL != (strFind =(CHAR *)  MCT_strnstr(szInputParam, szUpperFilter1, lTmpLen))))
    {
        MCT_sscanf(strFind + lTmpLen, "%s", szParam);
        bFind = BOOL_TRUE;
    }
    else if (NULL != pcFilter2)
    {
        lTmpLen = MCT_strnlen(pcFilter2, MAX_CFG_ITEM_LEN);
        if ((strFind = (CHAR *) MCT_strnstr(szInputParam, pcFilter2, lTmpLen)) ||
            (strFind = (CHAR *) MCT_strnstr(szInputParam, szUpperFilter2, lTmpLen)))
        {
            MCT_sscanf(strFind + lTmpLen, "%s", szParam);
            bFind = BOOL_TRUE;
        }
    }

    /* if all check ok, tranform the result */
    if (BOOL_TRUE == bFind)
    {
        lRet = ERR_COMMON_SUCCEED;
        if (CONFIG_DTY_STRING == ulType)
        {
            MCT_strncpy((CHAR *) pResult, szParam, MAX_CFG_ITEM_LEN -1);
        }
        else if (CONFIG_DTY_ULONGLONG == ulType)
        {
            DULONG *pTemp = (DULONG *) pResult;
            *pTemp = (DULONG) MCT_strtoll(szParam, &pcStop, 10);
        }
        else if (CONFIG_DTY_LONGLONG == ulType)
        {
            DLONG *pTemp = (DLONG *) pResult;
            (*pTemp) = MCT_strtoll(szParam, &pcStop, 10);
        }
        else if (CONFIG_DTY_LONG == ulType)
        {
            LONG *pTemp = (LONG *) pResult;
            (*pTemp) = MCT_strtol(szParam, &pcStop, 10);
        }
        else if (CONFIG_DTY_ULONG == ulType)
        {
            ULONG *pTemp = (ULONG *) pResult;
            (*pTemp) = (ULONG) MCT_strtol(szParam, &pcStop, 10);
        }
        else
        {
            lRet = ERR_INVALID_ITEM_VALUE;
        }
    }
    return lRet;
}

LONG config_mct::getCommonInputParam(CHAR *szInputParam, CHAR *pcFirFilter1, CHAR *pcFirFilter2, CHAR *pcSecFilter, ULONG ulType, VOID *pResult)
{
    CHAR *strFind = NULL;
    CHAR szUpperFirFilter1[MAX_CFG_ITEM_LEN] = {0};
    CHAR szUpperFirFilter2[MAX_CFG_ITEM_LEN] = {0};
    CHAR szUpperSecFilter[MAX_CFG_ITEM_LEN] = {0};
    CHAR szParam[MAX_CFG_ITEM_LEN] = {0};
    CHAR szSubParam[MAX_CFG_ITEM_LEN] = {0};
    CHAR *pcStop = NULL;
    BOOL_T bFind = BOOL_FALSE;
    LONG lRet = ERR_NOT_EXIST_ITEM;
    CHAR *strSub  = NULL;
    CHAR *pszSubParam = NULL;
    LONG lTmpLen = 0;

    if ((NULL == szInputParam) || (NULL == pcFirFilter1) || (NULL == pResult) )
    {
        return ERR_INPUT_PARAM_INFO;
    }

    if (NULL == pcSecFilter)
    {
        return getCommonInputParam(szInputParam, pcFirFilter1, pcFirFilter2, ulType, pResult);
    }


    string_toupper(pcFirFilter1, szUpperFirFilter1);
    if (NULL != pcFirFilter2)
    {
        string_toupper(pcFirFilter2, szUpperFirFilter2);
    }
    string_toupper(pcSecFilter, szUpperSecFilter);

    /* check the first filter string */
    lTmpLen = MCT_strnlen(pcFirFilter1, MAX_CFG_ITEM_LEN);
    if ((strFind = (CHAR *) MCT_strnstr(szInputParam, pcFirFilter1, lTmpLen)) ||
        (strFind = (CHAR *) MCT_strnstr(szInputParam, szUpperFirFilter1, lTmpLen)))
    {
        MCT_sscanf(strFind + lTmpLen, "%s", szParam);
        bFind = BOOL_TRUE;
    }
    else if (NULL != pcFirFilter2)
    {
        lTmpLen = MCT_strnlen(pcFirFilter2, MAX_CFG_ITEM_LEN);
        if ((strFind = (CHAR *) MCT_strnstr(szInputParam, pcFirFilter2, lTmpLen)) ||
            (strFind = (CHAR *) MCT_strnstr(szInputParam, szUpperFirFilter2, lTmpLen)))
        {
            MCT_sscanf(strFind + lTmpLen, "%s", szParam);
            bFind = BOOL_TRUE;
        }
    }

    /* if first check ok, then check the second filter string */
    if (BOOL_TRUE == bFind)
    {
        bFind = BOOL_FALSE;

        lTmpLen = MCT_strnlen(pcSecFilter, MAX_CFG_ITEM_LEN);
        if ((strSub = (CHAR *) MCT_strnstr(szParam, pcSecFilter, lTmpLen)) ||
            (strSub = (CHAR *) MCT_strnstr(szParam, szUpperSecFilter, lTmpLen)))
        {
           LONG i = lTmpLen;
           pszSubParam = szSubParam;
            while ((0 != *(strSub + i)) && ((';' != *(strSub + i)) && ('\"' != *(strSub + i))))
            {
                *pszSubParam = *(strSub + i);
                pszSubParam++;
                i++;
            }
            *pszSubParam = 0;

            bFind = BOOL_TRUE;
        }
    }

    /* if all check ok, tranform the result */
    if (BOOL_TRUE == bFind)
    {
        lRet = ERR_COMMON_SUCCEED;
        if (CONFIG_DTY_STRING == ulType)
        {
            MCT_strncpy((CHAR *) pResult, szSubParam, MAX_CFG_ITEM_LEN-1);
        }
        else if (CONFIG_DTY_ULONGLONG == ulType)
        {
            DULONG *pTemp = (DULONG *) pResult;
            *pTemp = (DULONG) MCT_strtoll(szSubParam, &pcStop, 10);
        }
        else if (CONFIG_DTY_LONGLONG == ulType)
        {
            DLONG *pTemp = (DLONG *) pResult;
            (*pTemp) = MCT_strtoll(szSubParam, &pcStop, 10);
        }
        else if (CONFIG_DTY_LONG == ulType)
        {
            LONG *pTemp = (LONG *) pResult;
            (*pTemp) = MCT_strtol(szSubParam, &pcStop, 10);
        }
        else if (CONFIG_DTY_ULONG == ulType)
        {
            ULONG *pTemp = (ULONG *) pResult;
            (*pTemp) = (ULONG) MCT_strtol(szSubParam, &pcStop, 10);
        }
        else
        {
            lRet = ERR_INVALID_ITEM_VALUE;
        }
    }

    return lRet;
}
